package com.suxin.ble.demo;

import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Build;
import android.os.Handler;
import android.printservice.PrinterDiscoverySession;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.constraint.ConstraintSet;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextPaint;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.scan.BleScanRuleConfig;
import com.clj.fastble.utils.HexUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class Main2Activity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = Main2Activity.class.getSimpleName();
    private String deviceName = "SuXin Iot";
    private static final int REQUEST_CODE_OPEN_GPS = 1;
    private static final int REQUEST_CODE_PERMISSION_LOCATION = 2;
    private Context mContext;
    private TextView tvCOresult;
    private TextView tvAccResult;
    private TextView tvPress;
    private ProgressDialog progressDialog;
    private boolean isDeviceConnect = false;
    private String status = "";
    private Button switchDevice;
    private Button btnVerification;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        initView();
        mContext = Main2Activity.this;
        BleManager.getInstance().init(getApplication());
        BleManager.getInstance()
                .enableLog(true)
                .setReConnectCount(1, 5000)
                .setConnectOverTime(20000)
                .setOperateTimeout(5000);
        checkPermissions();

    }

    private void initView() {

        progressDialog = new ProgressDialog(this);
        progressDialog.show();

        btnVerification = findViewById(R.id.btn_verification);
        btnVerification.setOnClickListener(this);

        switchDevice = findViewById(R.id.tv_cut_out);
        switchDevice.setOnClickListener(this);
        tvCOresult = findViewById(R.id.tv_co_result);
        tvAccResult = findViewById(R.id.tv_acc_result);
        tvPress = findViewById(R.id.tv_connect);

        tvPress.setOnClickListener(this);

    }

    private void checkPermissions() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (!bluetoothAdapter.isEnabled()) {
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, 0x02);
            return;
        }
        requestPermission();
    }

    private void requestPermission() {
        String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
        List<String> permissionDeniedList = new ArrayList<>();
        for (String permission : permissions) {
            int permissionCheck = ContextCompat.checkSelfPermission(this, permission);
            if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                onPermissionGranted(permission);
            } else {
                permissionDeniedList.add(permission);
            }
        }
        if (!permissionDeniedList.isEmpty()) {
            String[] deniedPermissions = permissionDeniedList.toArray(new String[permissionDeniedList.size()]);
            ActivityCompat.requestPermissions(this, deniedPermissions, REQUEST_CODE_PERMISSION_LOCATION);
        }
    }

    private void onPermissionGranted(String permission) {
        switch (permission) {
            case Manifest.permission.ACCESS_FINE_LOCATION:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !checkGPSIsOpen()) {
                    new AlertDialog.Builder(this)
                            .setTitle(R.string.notifyTitle)
                            .setMessage(R.string.gpsNotifyMsg)
                            .setNegativeButton(R.string.cancel,
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            finish();
                                        }
                                    })
                            .setPositiveButton(R.string.setting,
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                            startActivityForResult(intent, REQUEST_CODE_OPEN_GPS);
                                        }
                                    })

                            .setCancelable(false)
                            .show();
                } else {
                    setScanRule();
                    startScan();

                    Log.i(TAG, "onPermissionGranted: " + 222);
                }
                break;
        }
    }

    private void startScan() {
        BleManager.getInstance().scan(new BleScanCallback() {
            @Override
            public void onScanStarted(boolean success) {
                progressDialog.setMessage("正在扫描...");
                progressDialog.show();
            }

            @Override
            public void onLeScan(BleDevice bleDevice) {
                super.onLeScan(bleDevice);
            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                Log.i(TAG, "onScanning: " + "name:" + bleDevice.getDevice().getName() + "mac " + bleDevice.getDevice().getAddress());
                if (bleDevice.getDevice().getName().equals(deviceName)) {
                    progressDialog.setMessage("发现设备...");
                    BleManager.getInstance().cancelScan();
                    connnect(bleDevice);
                    Log.i(TAG, "onScanning: " + "连接设备");
                }
            }

            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                Log.i(TAG, "onScanFinished: " + scanResultList.size());
                if (scanResultList.size() == 0) {
                    showToast("未发现任何设备");
                    tvPress.setText("重新扫描！");
                    dismiss();
                } else {
                    for (int i = 0; i < scanResultList.size(); i++) {
                        if (!scanResultList.get(i).getName().equals(deviceName)) {
                            showToast("扫描结束,未找到设备");
                            tvPress.setText("重新扫描！");
                        }
                    }
                }
            }
        });
    }

    /*
     * 连接设备
     * */

    private void connnect(BleDevice bleDevice) {
        BleManager.getInstance().connect(bleDevice, new BleGattCallback() {
            @Override
            public void onStartConnect() {
                progressDialog.setMessage("连接设备...");
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                showToast("连接失败");
                dismiss();
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                tvPress.setText("连接成功！");
                progressDialog.setMessage("连接成功！");
                Log.i(TAG, "onConnectSuccess: " + BleManager.getInstance().getAllConnectedDevice().size());
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
//                        dismiss();
//                        setCOAndAcc();

                        progressDialog.setMessage("设备验证...");
                        startVerificaton();
                    }
                }, 1000);
//                设置一氧化碳数据 加速度数据

            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {

            }
        });
    }

    private void setCOAndAcc() {
        BleDevice device = Utils.getDevice(mContext);
        BluetoothGattService coService = Utils.getService(mContext, device, 1);
        final BluetoothGattCharacteristic coCharasterstic = Utils.getCharasterstic(coService, 0);

        BluetoothGattService accService = Utils.getService(mContext, device, 0);
        BluetoothGattCharacteristic accCharasterstic = Utils.getCharasterstic(accService, 0);

        if (coService == null || accService == null || coCharasterstic == null || accCharasterstic == null) {
            dismiss();
            showToast("连接失败");
            tvPress.setText("重新连接");
            return;
        }

        notifyCO(device, coCharasterstic);

        notifyAcc(device, accCharasterstic);

    }

    //    加速度 通知
    private void notifyAcc(BleDevice device, BluetoothGattCharacteristic accCharasterstic) {
        BleManager.getInstance().notify(
                device,
                accCharasterstic.getService().getUuid().toString(),
                accCharasterstic.getUuid().toString(),
                new BleNotifyCallback() {

                    @Override
                    public void onNotifySuccess() {
                        showToast("通知成功");
                        Log.i(TAG, "onNotifySuccess: " + "acc");
                    }

                    @Override
                    public void onNotifyFailure(final BleException exception) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
//                                    showToast("通知失败" + exception.getDescription().toString());
//                                    Log.i(TAG, "run: " + exception.getDescription().toString());
                            }
                        });
                    }

                    @Override
                    public void onCharacteristicChanged(final byte[] data) {

                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                String temp = Utils.switchResult(data);
//                                float acc = Utils.switchAcc(Integer.parseInt(temp, 16));
//                                tvAccResult.setText(new DecimalFormat("##.0").format(acc) + " m/s²");

                                float accResult;
                                int result = Integer.parseInt(temp, 16);//十进制
//                                Log.i(TAG, "run: " + "temp:" + temp + "result " + result);
                                if (result < 32678) {
                                    accResult = Utils.getAccResult(result);
                                } else {

                                    accResult = Utils.getAccResult1(result-32768);
                                }
                                Log.i(TAG, "run: " + "tvAccResul :" + tvAccResult);
                                BigDecimal bigDecimal = new BigDecimal(accResult).setScale(1, RoundingMode.DOWN);
                                tvAccResult.setText(bigDecimal + " m/s²");
                            }
                        });
                    }
                });
    }


    //一氧化塘浓度 通知
    private void notifyCO(BleDevice device, BluetoothGattCharacteristic charasterstic) {
        BleManager.getInstance().notify(
                device,
                charasterstic.getService().getUuid().toString(),
                charasterstic.getUuid().toString(),
                new BleNotifyCallback() {
                    @Override
                    public void onNotifySuccess() {
                        showToast("通知成功");
                        Log.i(TAG, "onNotifySuccess: " + "co");
                    }

                    @Override
                    public void onNotifyFailure(final BleException exception) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
//                                    showToast("通知失败" + exception.getDescription().toString());
                                Log.i(TAG, "run: " + exception.getDescription().toString());
//                                    tvPress.setText("重新连接");
                            }
                        });
                    }

                    @Override
                    public void onCharacteristicChanged(final byte[] data) {
                        setOnCharacteristicChanged(tvPress, data, "CO:");
                    }
                });

    }

    private void setOnCharacteristicChanged(final TextView tvAcc, final byte[] data, final String type) {
        runOnUiThread(new Runnable() {
            @SuppressLint("SetTextI18n")
            @Override
            public void run() {
                String old = HexUtil.formatHexString(data, false);
                String newResult = Utils.switchResult(data);
//                StringBuffer sb = new StringBuffer();
//                StringBuffer append = sb.append(result);
                tvCOresult.setText(Integer.parseInt(newResult, 16) + " ppm");
                Log.i(TAG, "run: cococococo:------------------>"  + "转换值：=="+Integer.parseInt(newResult,16)+ "old"+ old+"newResult" + newResult);
            }
        });
    }


    private void setScanRule() {

        BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder()
//                .setServiceUuids(serviceUuids)      // 只扫描指定的服务的设备，可选
                .setDeviceName(true, "SuXin Iot")   // 只扫描指定广播名的设备，可选
//                .setDeviceMac(mac)                  // 只扫描指定mac的设备，可选
                .setAutoConnect(true)      // 连接时的autoConnect参数，可选，默认false
                .setScanTimeOut(10000)              // 扫描超时时间，可选，默认10秒
                .build();
        BleManager.getInstance().initScanRule(scanRuleConfig);
    }

    private boolean checkGPSIsOpen() {
        LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        if (locationManager == null)
            return false;
        return locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER);
    }

    @Override
    public final void onRequestPermissionsResult(int requestCode,
                                                 @NonNull String[] permissions,
                                                 @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case REQUEST_CODE_PERMISSION_LOCATION:
                if (grantResults.length > 0) {
                    for (int i = 0; i < grantResults.length; i++) {
                        if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                            onPermissionGranted(permissions[i]);
                        } else {
                            finish();
                        }
                    }
                }
                break;
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 0x02 && resultCode == RESULT_OK) {
            requestPermission();
        } else {
            finish();
        }

        if (requestCode == REQUEST_CODE_OPEN_GPS) {
            if (checkGPSIsOpen()) {
                setScanRule();
                startScan();
                Log.i(TAG, "onActivityResult: " + 11);
            }
        }

    }

    private void dismiss() {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume: ");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        BleManager.getInstance().disconnectAllDevice();
        BleManager.getInstance().destroy();
        Log.i(TAG, "onDestroy: ");
    }


    private void showToast(String msg) {
        Toast.makeText(Main2Activity.this, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {
            case R.id.btn_verification:
                //14 验证成功 15 验证失败
                startVerificaton();
                break;
            case R.id.tv_connect:
                BleManager.getInstance().disconnectAllDevice();
                BleManager.getInstance().destroy();
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        startScan();
                    }
                }, 1000);
                break;

            case R.id.tv_cut_out:
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        connectOrDisConnectDevice();
                        Log.i(TAG, "run: " + "switch device");
                    }
                }, 200);


                break;
        }
    }

    //验证蓝牙
    private void startVerificaton() {
        final String verification = "4e5441494c5553574e4945585542530000000000";
        Log.i(TAG, "startVerificaton: " + HexUtil.hexStringToBytes("verification"));
        final BleDevice device = Utils.getDevice(mContext);
        List<BluetoothGattService> verificationService = BleManager.getInstance().getBluetoothGattServices(device);
        if (verificationService == null) {
            showToast("暂无设备连接");
            return;
        }
        List<BluetoothGattCharacteristic> verificationCharateristic = verificationService.get(2).getCharacteristics();
        final BluetoothGattCharacteristic characteristic = verificationCharateristic.get(0);

        BleManager.getInstance().write(device,
                characteristic.getService().getUuid().toString(),
                characteristic.getUuid().toString(),
                HexUtil.hexStringToBytes(verification),
                new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(int current, int total, byte[] justWrite) {
                        Log.i(TAG, "onWriteSuccess:  认证成功" + "-->");
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                verificationNotify(device, characteristic, verification);
                            }
                        }, 300);
                    }

                    @Override
                    public void onWriteFailure(BleException exception) {
                        Log.i(TAG, "onWriteFailure: 认证失败 " + exception.getDescription().toString());
                        progressDialog.setMessage("认证失败");
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                dismiss();
                            }
                        }, 2000);
                    }
                });

    }

    private void verificationNotify(BleDevice device, BluetoothGattCharacteristic characteristic, String verification) {
        BleManager.getInstance().notify(device,
                characteristic.getService().getUuid().toString(),
                characteristic.getUuid().toString(),
                new BleNotifyCallback() {
                    @Override
                    public void onNotifySuccess() {
                        Log.i(TAG, "onNotifySuccess: ");
                    }

                    @Override
                    public void onNotifyFailure(BleException exception) {
                        Log.i(TAG, "onNotifyFailure: " + exception.getDescription());
//                            showToast("设备认证失败");
                        dismiss();
                    }

                    @Override
                    public void onCharacteristicChanged(byte[] data) {
                        Log.i(TAG, "onCharacteristicChanged: " + HexUtil.formatHexString(data, true));
                        String s = HexUtil.formatHexString(data, false);
                        if (s.equals("14")) {
                            showToast("验证成功");
                            setCOAndAcc();
                        } else if (s.equals("15")) {
                            showToast("验证失败");
                        }
                        dismiss();
                    }
                }
        );
    }

    private void connectOrDisConnectDevice() {
        BleDevice device = Utils.getDevice(mContext);
        BluetoothGattService service = Utils.getService(mContext, device, 1);
        BluetoothGattCharacteristic charasterstic = Utils.getCharasterstic(service, 1);
        if (device == null || service == null || charasterstic == null) {
            showToast("暂无设备连接");
            tvPress.setText("重新连接");
            return;
        }

        BleManager.getInstance().write(device,
                charasterstic.getService().getUuid().toString(),
                charasterstic.getUuid().toString(),
                HexUtil.hexStringToBytes(getCurrentStatus()),
                new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(int current, int total, byte[] justWrite) {
                        Log.i(TAG, "onWriteSuccess: ");
                        if (isDeviceConnect) {
                            switchDevice.setText("柴油机已开启");
                        } else {
                            switchDevice.setText("柴油机已断开");
                        }
                    }

                    @Override
                    public void onWriteFailure(BleException exception) {
                        Log.i(TAG, "onWriteFailure: " + exception.getDescription().toString());
                    }
                }
        );

    }

    private String getCurrentStatus() {
        if (isDeviceConnect) {
            status = "02";
        } else {
            status = "01";
        }
        isDeviceConnect = !isDeviceConnect;
        return status;
    }


}
